package com.leyou.item.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.common.pojo.PageResult;
import com.leyou.item.Bo.SpuBo;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.mapper.StockMapper;
import com.leyou.item.pojo.*;

import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.persistence.Transient;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Log4j2
@Service
public class GoodsService {
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private BrandService brandService;
    @Autowired
    private SpuDetailMapper spuDetailMapper;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private StockMapper stockMapper;

    //发送消息;消息携带商品spu的id,和操作类型
    private void sendMessage(Long id, String type) {
        try {//发送信息不能影响主业务
            this.amqpTemplate.convertAndSend("ly.item.exchange", "item." + type, id);
        } catch (AmqpException e) {
            e.printStackTrace();
            log.error("{}商品信息发送失败,商品id:{}" + type, id, e.getMessage());
        }

    }

    //==========================================================
    //查询分页信息
    public PageResult<SpuBo> querySpuByPage(Integer page, Integer rows, String key, Boolean saleable) {
        //分页助手查询分页信息
        PageHelper.startPage(page, Math.min(rows, 100));
        //创建查询模板
        Example example = new Example(Spu.class);
        //创建查询条件
        Example.Criteria criteria = example.createCriteria();
        //判断是否上架,saleable不为null,即是true
        if (saleable != null) {
            criteria.andEqualTo("saleable", saleable);
        }
        //搜索条件商品名称和标题
        if (StringUtils.isNotBlank(key)) {
            criteria.andLike("title", "%" + key + "%");
        }

        Page<Spu> pageInfo = (Page<Spu>) this.spuMapper.selectByExample(example);
        List<SpuBo> list = pageInfo.getResult().stream().map(spu -> {
            //把spu复制给spubo,相当于spuBo.setName(spu.getName)
            SpuBo spuBo = new SpuBo();
            BeanUtils.copyProperties(spu, spuBo);
            //查询spu商品分类,三级联查
            List<String> cnames = this.categoryService.queryNamesByIds(
                    Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
            //添加商品分类列表到spubo里..StringUtils.join把集合以什么相连
            spuBo.setCname(StringUtils.join(cnames, "/"));
            //添加品牌名到spubo 中
            Brand brand = this.brandService.queryBrandById(spu.getBrandId());
            spuBo.setBname(brand.getName());
            return spuBo;
        }).collect(Collectors.toList());

        return new PageResult<>(pageInfo.getTotal(), list);
    }

    //===============================================================
    //保存商品
    @Transient
    public void saveGoods(SpuBo spuBo) {
        //由于保存涉及四个表。分别保存数据
        //1:先保存sku表数据。由于前端数据没有添加上架，vaild,创建时间和最后提价实间，自己添加并保存
        spuBo.setValid(true);
        spuBo.setSaleable(true);
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        this.spuMapper.insertSelective(spuBo);

        //保存分类详情表.由于详情表用的是spu的id所以，设置详情表的id
        spuBo.getSpuDetail().setSpuId(spuBo.getId());
        this.spuDetailMapper.insertSelective(spuBo.getSpuDetail());

        List<Sku> skus = spuBo.getSkus();
        Long id = spuBo.getId();
        for (Sku sku : skus) {
            //由于前端传过来的数据，小于数据库要的数据，所以动态加入数据库需要的数据
            //判断是否有效，有效了才保存
            if (!sku.getEnable()) {
                continue;
            }
            sku.setCreateTime(new Date());
            sku.setLastUpdateTime(sku.getCreateTime());
            sku.setSpuId(id);
            this.skuMapper.insertSelective(sku);

            //保存库存数量，和sku公用id
            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            stockMapper.insertSelective(stock);
        }

        sendMessage(spuBo.getId(), "insert");//调用发送信息通知其他服务

        //保存特有属性sku,由于sku是集合，所以，遍历保存。
        // saveSkuAndStock(spuBo.getSkus(), spuBo.getId());//不能调用

    }

    //===============================================================================
    //根据spuid 查询商品详情
    public SpuDetail querySpuDetailById(Long spuId) {
        SpuDetail spuDetail = new SpuDetail();
        spuDetail.setSpuId(spuId);
        return this.spuDetailMapper.selectOne(spuDetail);
    }

    //根据id查询sku回显信息.把库存也查出来
    public List<Sku> querySkuBySpuId(Long spuId) {
        Sku sku = new Sku();
        sku.setSpuId(spuId);
        List<Sku> skus = this.skuMapper.select(sku);
        for (Sku skus1 : skus) {
          /*  Stock stock = new Stock();
            stock.setSkuId(skus1.getId());
            Stock stock1 = this.stockMapper.selectOne(stock);
            skus1.setStock(stock1.getStock());*/
            skus1.setStock(this.stockMapper.selectByPrimaryKey(skus1.getId()).getStock());
        }
        return skus;
    }

    //修改商品
    @Transient//修改商品sku，新增。修改，下架；
    public void update(SpuBo spuBo) {
        //修改spu全局属性
        spuBo.setCreateTime(new Date());
        spuBo.setLastUpdateTime(spuBo.getCreateTime());
        spuBo.setValid(true);
        spuBo.setSaleable(true);
        this.spuMapper.updateByPrimaryKeySelective(spuBo);
        //修改原来的详情spuDetail
        spuBo.getSpuDetail().setSpuId(spuBo.getId());
        this.spuDetailMapper.updateByPrimaryKeySelective(spuBo.getSpuDetail());

        //修改商品sku，新增。修改，下架；
        Sku sku1 = new Sku();
        sku1.setSpuId(spuBo.getId());
        List<Sku> oldSkus = this.skuMapper.select(sku1);//原数据
        List<Sku> newSkus = spuBo.getSkus();//新增数据
        newSkus.forEach(newSku -> {
            //判断新增数据，有没有sku的id，有id即是修改(原数据减去修改就是下架)，没有id就是新增
            if (newSku.getId() == null) {//没有id就是新增sku
                newSku.setSpuId(spuBo.getId());//前端处理没有传过来spuId
                newSku.setCreateTime(new Date());
                newSku.setLastUpdateTime(newSku.getCreateTime());
                this.skuMapper.insertSelective(newSku);
                //保存库存数量，和sku公用id
                Stock stock = new Stock();
                stock.setSkuId(newSku.getId());
                stock.setStock(newSku.getStock());
                stockMapper.insertSelective(stock);

            } else {//有sku的id即是修改

                newSku.setSpuId(spuBo.getId());//前端处理没有传过来spuId
                newSku.setLastUpdateTime(new Date());
                this.skuMapper.updateByPrimaryKeySelective(newSku);
                //保存库存数量，和sku公用id
                Stock stock = new Stock();
                stock.setSkuId(newSku.getId());
                stock.setStock(newSku.getStock());
                this.stockMapper.updateByPrimaryKeySelective(stock);
                oldSkus.removeIf(oldSku -> oldSku.getId().longValue() == newSku.getId().longValue());
            }
            //此时未必有下架的
            oldSkus.forEach(oldSku -> {
                //最后修改时间
                oldSku.setLastUpdateTime(new Date());
                //设置下架时间
                oldSku.setEnable(false);
                this.skuMapper.updateByPrimaryKeySelective(oldSku);
            });

        });

        sendMessage(spuBo.getId(), "update");//更改数据通知
    }

    //====================================
    //删除商品
    @Transient
    public void deleteGoods(Long spuId) {
        //考虑删除多张表数据，先删除最内层的数据，sku,库存。详情表，spu;
        deleteSkuAndStockBySpuId(spuId);//删除sku和库存
        //删除详情
        this.spuDetailMapper.deleteByPrimaryKey(spuId);
        this.spuMapper.deleteByPrimaryKey(spuId);//删除spu

        sendMessage(spuId, "delete");//删除商品
    }


    //把保存sku信息抽成一个方法：
    private void saveSkuAndStock(List<Sku> skus, Long id) {
        for (Sku sku : skus) {
            //由于前端传过来的数据，小于数据库要的数据，所以动态加入数据库需要的数据
            //判断是否有效，有效了才保存
            if (!sku.getEnable()) {//判断前端是否勾选sku上架选项；如果勾选是true；不勾选不保存
                continue;
            }
            sku.setCreateTime(new Date());
            sku.setLastUpdateTime(sku.getCreateTime());
            sku.setSpuId(id);
            this.skuMapper.insertSelective(sku);

            //保存库存数量，和sku公用id
            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            stockMapper.insertSelective(stock);
        }
    }

    //根据spuid删除库存和sku特有属性的方法
    private void deleteSkuAndStockBySpuId(Long id) {
        List<Sku> skus1 = querySkuBySpuId(id);
        for (Sku sku : skus1) {
            this.stockMapper.deleteByPrimaryKey(sku.getId());
            this.skuMapper.deleteByPrimaryKey(sku.getId());
        }
    }

    //下架
    public void updateGoodsDownById(Long id) {
        //下架spu
        Spu spu = new Spu();
        spu.setSaleable(false);//需要下架的商品，需要修改的字段
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", id);//根据什么查询到需要修改的数据
        this.spuMapper.updateByExampleSelective(spu, example);
        //sku也下架
        Example example1 = new Example(Sku.class);
        Example.Criteria criteria1 = example.createCriteria();


//  根据spuid 查 skulist
        Sku sku1 = new Sku();
        sku1.setSpuId(id);
        List<Sku> skus = this.skuMapper.select(sku1);
        for (Sku skus1 : skus) {
            sku1.setEnable(false);
            criteria1.andEqualTo("id", sku1.getId());
            this.skuMapper.updateByExampleSelective(sku1, example1);
        }
    }

    //上架
    public void updateGoodsUpById(Long id) {
        //下架spu
        Spu spu = new Spu();
        spu.setSaleable(true);//需要上架的商品，需要修改的字段
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", id);//根据什么查询到需要修改的数据
        this.spuMapper.updateByExampleSelective(spu, example);

        // 根据spuid 查 skulist
        Example example1 = new Example(Sku.class);
        Example.Criteria criteria1 = example.createCriteria();
        Sku sku1 = new Sku();
        sku1.setSpuId(id);
        List<Sku> skus = this.skuMapper.select(sku1);
        for (Sku skus1 : skus) {
            sku1.setEnable(true);
            criteria1.andEqualTo("id", sku1.getId());
            this.skuMapper.updateByExampleSelective(sku1, example1);
        }

    }

    //根据spuid查询spu
    public Spu querySpuById(Long id) {
        Spu spu = new Spu();
        spu.setId(id);
        return this.spuMapper.selectOne(spu);
    }

    //根据skuid查询sku
    public Sku querySkuBySkuId(Long id) {
        Sku sku = new Sku();
        sku.setId(id);
        return this.skuMapper.selectOne(sku);
    }
}
